package com.yitiao.multithread.printabc;

/**
 * <h3>三个线程负责打印任务</h3>
 * <p>wait、notifyAll必须在synchronized内使用</p>
 * <p>notifyAll() 唤醒所有线程</p>
 * <p>调用wait之后，synchronized锁会直接晋升到重量级锁</p>
 * @author libiao
 */
public class PrintAbcDemo_1 {

    private Integer signal = 0;

    public synchronized void printA() {
        while (signal != 0) {
            try {
                wait(); // 调用wait之后，synchronized锁会直接晋升到重量级锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("a");
        signal = 1;
        notifyAll(); // 唤醒所有进入wait状态的线程,如何唤醒指定线程？
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printB() {
        while (signal != 1) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("b");
        signal = 2;
        notifyAll();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printC() {
        while (signal != 2) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("c");
        signal = 0;
        notifyAll();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        PrintAbcDemo_1 printAbcDemo1 = new PrintAbcDemo_1();

        Thread printaThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    printAbcDemo1.printA();
                }
            }
        });
        Thread printbThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    printAbcDemo1.printB();
                }
            }
        });
        Thread printcThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    printAbcDemo1.printC();
                }
            }
        });
        printaThread.start();
        printbThread.start();
        printcThread.start();
        Thread.yield();  // 当前线程标志自己可以让出时间片给同优先级的线程，但并不是直接停止
//        System.out.println("yield"); // 依然会被执行
    }

}
